package com.lt.cmn.service.Impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lt.cmn.listener.DictListener;
import com.lt.cmn.mapper.DictMapper;
import com.lt.cmn.service.DictService;
import com.lt.hospital.model.cmn.Dict;
import com.lt.hospital.model.hosp.Hospital;
import com.lt.hospital.vo.cmn.DictEeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//实现类也是mp帮忙写好了的，前面写mapper文件，然后后面就写实体类
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    //这个其实可以不写的，ServiceImpl<DictMapper, Dict>在内部已经帮忙写好了 可以看源码
    @Autowired
    private DictMapper dictMapper;

    //根据数据id查询子数据列表
    @Override
    //缓存服务，表示开启缓存，查过一次数据放入缓存中，第二次查询加速查询速度，之后都得开启redis才能启用运行成功咯
    @Cacheable(value = "dict",keyGenerator = "keyGenerator")
    public List<Dict> findChildId(Long id) {
        //条件查询
        QueryWrapper<Dict> wrapper =new QueryWrapper<>();
        //精确匹配
        wrapper.eq("parent_id",id); //select * from dict where parent_id = id
        //将查询的数据放入集合当中
        List<Dict> list = dictMapper.selectList(wrapper);

        //向list集合每个dict对象中设置hasChildren
        for (Dict dict:list){
            Long dictId = dict.getId();//获取到每条记录的id
            boolean isChild = isChild(dictId); //判断这些数据是否有子节点
            dict.setHasChildren(isChild);//设置是否有子节点
        }
        return list;
    }

    /**
     * 根据dictCode查询下级节点数据
     * @param dictCode
     * @return
     */
    @Override
    public List<Dict> queryByDictCode(String dictCode) {
        //通过自己写的这个方法queryDictByValue得到dict对象
        Dict dict =this.queryDictByValue("dict_code",dictCode);
        List<Dict> list = findChildId(dict.getId());
        return list;
    }

    //判断id下面是否有子节点
    private boolean isChild(Long id){
        //条件查询
        QueryWrapper<Dict> wrapper =new QueryWrapper<>();
        //精确匹配
        wrapper.eq("parent_id",id);
        Integer count =dictMapper.selectCount(wrapper);//这个是检查匹配后的数据条数的
        return count>0;//如果大于0表示有数据返回为true，没数据返回为false
    }

    /**
     * 导出数据字典数据
     * @param httpServletResponse
     */
    @Override
    public void exportDictData(HttpServletResponse httpServletResponse) {
        //Content-Type（内容类型） 这里表示返回的是excel表格类型
        httpServletResponse.setContentType("application/vnd.ms-excel");
        //设置字符编码
        httpServletResponse.setCharacterEncoding("utf-8");
        //文件名称
        String fileName = "dict";
        //Content-disposition 表示的是下载，这个信息头会告诉浏览器这个文件的名字和类型
        httpServletResponse.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");

        //查询出数据字典内容,传入null表示无条件，说明查询的就是全部了
        List<Dict> list = dictMapper.selectList(null);
        //创建vo集合对象
        List<DictEeVo> dictEeVoList = new ArrayList<>();

        for (Dict dict:list){
            //创建dictEeVo对象
            DictEeVo dictEeVo = new DictEeVo();
            //将dict对象付给dictEeVo对象，这是spring封装好的方法可以直接拿来用了
            BeanUtils.copyProperties(dict,dictEeVo);
            dictEeVoList.add(dictEeVo);
        }

        try {
            //EasyExcel这是个插件，第一个参数传入了字节输出流，第二个参数是传给excel显示哪些字段的 sheet表示的名称 ，doWriter里面传入需要的数据
            EasyExcel.write(httpServletResponse.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictEeVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 导入数据字典
     * @param file
     */
    @Override
    //表示缓存数据清空，再往里面加数据，重新用缓存
    @CacheEvict(value = "dict", allEntries=true)
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(dictMapper)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getDictName(String dictCode, String value) {
        //判断dictCode是否为空，如果是空的，通过值找到name
        if(StringUtils.isEmpty(dictCode)){
            Dict dict = this.queryDictByValue("value", value);
            return dict.getName();
        }else {
            //通过dictCode查询到parentId
            Dict codeDict = this.queryDictByValue("dict_code", dictCode);
            Long parentId = codeDict.getId();

            //查询父id和值都匹配的情况
            QueryWrapper<Dict> wrapper =new QueryWrapper<>();
            wrapper.eq("parent_id",parentId);//精确查询
            wrapper.eq("value",value);//精确查询
            Dict finalDict = dictMapper.selectOne(wrapper);

            return finalDict.getName();
        }
    }



    /**
     * wrapper.eq(,);对这个方法进行封装，弊端，条件只能有一条，可以写成数组，传入的就更多了
     * @param column
     * @param param
     * @return
     */
    private Dict queryDictByValue(String column,Object param){
        QueryWrapper<Dict> wrapper =new QueryWrapper<>();
        wrapper.eq(column,param);//精确查询
        Dict dict = dictMapper.selectOne(wrapper);
        return dict;
    }
}
